package civicinity.ist.psu.edu.share;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.json.JSONException;
import org.json.JSONObject;

import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.FacebookError;
import com.facebook.android.Util;
import com.facebook.android.Facebook.DialogListener;

import civicinity.ist.psu.edu.CivicinityLogin;
import civicinity.ist.psu.edu.CivicinityMainpage;
import civicinity.ist.psu.edu.R;
import civicinity.ist.psu.edu.CivicinityLogin.SampleRequestListener;
import civicinity.ist.psu.edu.R.id;
import civicinity.ist.psu.edu.R.layout;
import civicinity.ist.psu.edu.constants.Constants;
import civicinity.ist.psu.edu.databases.CivicinityDatabase;
import civicinity.ist.psu.edu.facebook.BaseRequestListener;
import civicinity.ist.psu.edu.facebook.SessionStore;
import civicinity.ist.psu.edu.utils.MyLocation;
import civicinity.ist.psu.edu.utils.UploadHandler;
import civicinity.ist.psu.edu.utils.MyLocation.LocationResult;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Bitmap.CompressFormat;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast;

public class CivicinityMyView extends Activity{

	private String mImagePath = null;
	private ImageView photoImg;
	private EditText commentTxt;
	private Button uploadBtn;
	private Button revertBtn;
	private CheckBox checkBox;
	//private Spinner mSpinner;
	
	private CivicinityDatabase mDB;
	
	private String mCategory = "";
	
	private double mLatitude = 0.0;
	private double mLongitude = 0.0;
	private float mAccuracy = 0;
	
	private int mReturnID;
	private int mSelectedItem = 0;
	private SharedPreferences mPref;
	
	private Facebook mFacebook;
	private AsyncFacebookRunner mAsyncRunner;
	private ProgressDialog mDialog = null;
	
	private boolean checkBoxChecked = false;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
	    super.onCreate(savedInstanceState);
	    setContentView(R.layout.my_view);
	    
	    Intent gIntent = getIntent();
	    mImagePath = gIntent.getExtras().getString("image_path");
	    
	    mDB = new CivicinityDatabase(this);
	    mPref = PreferenceManager.getDefaultSharedPreferences(this);
	    
	    MyLocation myLocation = new MyLocation();
	    myLocation.getLocation(this, locationResult);
	    
	    if(mImagePath == null) {
	    	Toast.makeText(this, "Error in fetching a photo", Toast.LENGTH_SHORT).show();
	    	finish();
	    }
	    
	    photoImg = (ImageView)findViewById(R.id.photo);
	    commentTxt = (EditText)findViewById(R.id.comment);
	    uploadBtn = (Button)findViewById(R.id.upload);
	    revertBtn = (Button)findViewById(R.id.revert);
	    checkBox = (CheckBox)findViewById(R.id.facebook_upload);
	    //mSpinner = (Spinner)findViewById(R.id.spinner);
	    
	    /*
	    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_single_choice, Constants.SHARE_CATEGORY);
	    mSpinner.setAdapter(adapter);
	    mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {

			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				// TODO Auto-generated method stub
				int item = mSpinner.getSelectedItemPosition();
				mSelectedItem = item;
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO Auto-generated method stub
				
			}
	    	
	    });
	    */
	    // If there's a cached image in the sdcard, retrieve it; otherwise, show that on the webpage 
		//String imagePath = Constants.CIVICINITY_PHOTO_PATH + mCameraImageID + ".jpg";
		
		Log.i("K", "imagePath : " + mImagePath);
		
		File checkExistFile = new File(mImagePath);
		if(checkExistFile.exists()) {
			//speciesImage.
			Bitmap resizedPhoto = ShowPhotoTaken(mImagePath);
			//photoImg.setImageBitmap(overlay(resizedPhoto));
			photoImg.setImageBitmap(resizedPhoto);
		}
		else {
			Toast.makeText(this, "Error in fetching a photo", Toast.LENGTH_SHORT).show();
		}
		
		checkBox.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				if(checkBox.isChecked()) {
					checkBoxChecked = true;
				}
				else {
					checkBoxChecked = false;
				}
			}
		});
		
		
		uploadBtn.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				if(mPref.getBoolean("guest_mode", false)) {
					Toast.makeText(CivicinityMyView.this, "Logged in as 'GUEST', cannot upload the data to the server", Toast.LENGTH_SHORT).show();
				}
				else {
					if(mLatitude == 0.0 || mLongitude == 0.0) {
						Toast.makeText(CivicinityMyView.this, "Please wait while finding your location", Toast.LENGTH_SHORT).show();
					}
					else {
						
						long timeInMillis = System.currentTimeMillis();
						mReturnID = mDB.setShareMe(mImagePath, Constants.SHARE_CATEGORY[mSelectedItem], commentTxt.getText().toString(), timeInMillis, mLatitude, mLongitude, mAccuracy);
						
						// if Facebook upload CheckBox clicked but the user is not logged in with Facebook account, double check that the
						// user should login with facebook id.
						if(checkBoxChecked) {
							if(!mPref.getBoolean("facebook", false)) {
								showDialogLoginFacebook();						
							}
							else {
								Toast.makeText(CivicinityMyView.this, "Successfully added. Your data will be uploaded soon.", Toast.LENGTH_SHORT).show();
								
								// upload the values to the server.
								UploadHandler uploadH = new UploadHandler(CivicinityMyView.this);
								uploadH.upload(mReturnID, true);
								
								// move to mainpage
								finish();
								Intent intent = new Intent(CivicinityMyView.this, CivicinityMainpage.class);
								intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
								startActivity(intent);
							}
						}
						else {
							Toast.makeText(CivicinityMyView.this, "Successfully added. Your data will be uploaded soon.", Toast.LENGTH_SHORT).show();
							
							// upload the values to the server.
							UploadHandler uploadH = new UploadHandler(CivicinityMyView.this);
							uploadH.upload(mReturnID, false);
							
							// move to mainpage
							finish();
							Intent intent = new Intent(CivicinityMyView.this, CivicinityMainpage.class);
							intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
							startActivity(intent);
						}
					}
				}			
			}
		});
		
		revertBtn.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				finish();
			}
		});
	    
	    // TODO Auto-generated method stub
	}
	
	public void showDialogLoginFacebook() {
		
		Toast.makeText(CivicinityMyView.this, "Successfully added. Your data will be uploaded soon.", Toast.LENGTH_SHORT).show();
		
		// ask the user to login with Facebook account
		new AlertDialog.Builder(CivicinityMyView.this)
    	.setTitle("Need to login Facebook")
    	.setMessage("To upload your photo to Facebook, you need to login with a Facebook account again. Proceed?")
		.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				mFacebook = new Facebook("263466350349965");
				mAsyncRunner = new AsyncFacebookRunner(mFacebook);
				
				mFacebook.authorize(CivicinityMyView.this, new String[] {"offline_access", "email", "read_stream"}, new DialogListener(){

					@Override
					public void onComplete(Bundle values) {
						// TODO Auto-generated method stub
				
						// Login success and save user's profile
			        	if(Looper.myLooper() == null) {
			        		Looper.prepare();
			        	}
			        	
			        	mDialog = ProgressDialog.show(CivicinityMyView.this, "Loading...", "Logging into Civicinity mobile application with Facebook account...", true);
						
						mAsyncRunner.request("me", new SampleRequestListener());
					}

					@Override
					public void onFacebookError(FacebookError e) {
						// TODO Auto-generated method stub
						e.printStackTrace();
					}

					@Override
					public void onError(DialogError e) {
						// TODO Auto-generated method stub
						e.printStackTrace();
					}

					@Override
					public void onCancel() {
						// TODO Auto-generated method stub
					}
				});
			}
		})
		.setNegativeButton("No", null)
		.show();
	}
	
	public LocationResult locationResult = new LocationResult() {

		@Override
		public void gotLocation(Location location) {
			// TODO Auto-generated method stub
			mLatitude = location.getLatitude();
			mLongitude = location.getLongitude();
			mAccuracy = location.getAccuracy();
			
			Log.i("K", "Accuracy : " + mAccuracy);
		}
	};
	
	private Bitmap overlay(Bitmap... bitmaps) {
		
		if (bitmaps[0].equals(null))
			return null;

		Bitmap bmOverlay = Bitmap.createBitmap(130, 130, Bitmap.Config.ARGB_4444);

		Canvas canvas = new Canvas(bmOverlay);
		for (int i = 0; i < bitmaps.length; i++)
			canvas.drawBitmap(bitmaps[i], new Matrix(), null);

		return bmOverlay;
	}
	
	protected static final int MAX_IMAGE_WIDTH = 1280;
	protected static final int MAX_IMAGE_HEIGHT = 960;
	private Bitmap scaledImage;
	
	public Bitmap ShowPhotoTaken(String path) {
		try {
			BitmapFactory.Options options = new BitmapFactory.Options();
			
			options.inJustDecodeBounds = true;
			BitmapFactory.decodeFile(path, options);
			
			int factor =  Math.max(options.outWidth / MAX_IMAGE_WIDTH, options.outHeight / MAX_IMAGE_HEIGHT);
			
			options.inSampleSize = msb32(factor);
			options.inPurgeable = true;
			options.inInputShareable = true;
			options.inJustDecodeBounds = false;
			
			Bitmap image = BitmapFactory.decodeFile(path, options);
			
			
			if(image.getWidth() > MAX_IMAGE_WIDTH || image.getHeight() > MAX_IMAGE_HEIGHT) {
				float scale = Math.min(MAX_IMAGE_WIDTH / (float)image.getWidth(), 
						MAX_IMAGE_HEIGHT / (float)image.getHeight());
				
				int newWidth = (int)((image.getWidth() * scale) + 0.5f);
				int newHeight = (int)((image.getHeight() * scale) + 0.5f);
				
				scaledImage = Bitmap.createScaledBitmap(image, newWidth, newHeight, true);
				image.recycle();	
			}
			else {
				scaledImage = image;
			}
			
			OutputStream os = new FileOutputStream(path);
			scaledImage.compress(CompressFormat.JPEG, 80, os);
			os.close();
			
			int width = scaledImage.getWidth();
		   	int height = scaledImage.getHeight();
		   	
		    Bitmap resized_bitmap = null;
		    // set new width and height of the phone_image
		    int new_width = 250;
		    int new_height = 250;
		   	
		   	float scale_width = ((float) new_width) / width;
		   	float scale_height = ((float) new_height) / height;
		   	Matrix matrix = new Matrix();
		   	matrix.postScale(scale_width, scale_height);
		   	resized_bitmap = Bitmap.createBitmap(scaledImage, 0, 0, width, height, matrix, true);
			
		   	return resized_bitmap;
			
		}
		catch(FileNotFoundException e){
			
		}
		catch(IOException e) {
			
		}
		catch(OutOfMemoryError e){
			
		}
		return null;
	}
	
	private void showCategory() {
    	
    	final CharSequence[] categoryList = {"Event", "Food", "Building", "Plant/Flower", "Not specified"} ;

    	// initialize the boolean values to false.
    	final boolean[] select = new boolean[categoryList.length];
    	for(int i = 0 ; i < select.length ; i++) {
    		select[i] = false;
    	}
    	
    	// add category
    	new AlertDialog.Builder(CivicinityMyView.this)
    	.setTitle("Choose Category")
    	.setSingleChoiceItems(categoryList, -1, new DialogInterface.OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				select[which] = true;
			}
		})
		.setPositiveButton("Choose", new DialogInterface.OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				for(int i = 0 ; i < select.length ; i++) {
					if(select[i]) {
						// if "Add New Category" is chosen.
						Toast.makeText(CivicinityMyView.this, categoryList[i] + " is selected!", Toast.LENGTH_SHORT).show();
						mCategory = String.valueOf(categoryList[i]);
					}
				}
			}
		})
		.setNegativeButton("Back", null)
		.show();
    }
	
    private int msb32(int x) {
        x |= (x >> 1);
        x |= (x >> 2);
        x |= (x >> 4);
        x |= (x >> 8);
        x |= (x >> 16);
        return (x & ~(x >> 1));
    }
    
    public class SampleRequestListener extends BaseRequestListener {

        public void onComplete(final String response, final Object state) {

    		
            // then post the processed result back to the UI thread
            // if we do not do this, an runtime exception will be generated
            // e.g. "CalledFromWrongThreadException: Only the original
            // thread that created a view hierarchy can touch its views."
            CivicinityMyView.this.runOnUiThread(new Runnable() {
                public void run() {
    	    		// create the account from our database based on the username
    	    		// so far the password is randomly generated.
    	    		// or we can ask the user to put the username or password. (it is like creating the new account from our system)
    	    		// TODO: connect to our local server.
                	// process the response here: executed in background thread
                    Log.d("Facebook-Example", "Response: " + response.toString());
                    JSONObject json;
                    String name = "";
					try {
						json = Util.parseJson(response);
						name = json.getString("name");  
					} catch (JSONException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (FacebookError e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
                      	
					SessionStore.save(mFacebook, CivicinityMyView.this);
                	
                    // save the username into the sharedpreferences
                    SharedPreferences.Editor editor = mPref.edit();
    				editor.putString("username", name);
    				editor.putInt("user_id", 1); // temporary put id as "admin" (id=1) TODO : not decided what to do yet.
    				editor.putString("password", name); // temporaray put password as sme as username TODO : need to do something later.
    				editor.putBoolean("loggedin", true);
    	    		editor.putBoolean("guest_mode", false);
    	    		editor.putBoolean("facebook", true);
    	    		editor.commit();
    	    		
    	    		// upload the values to the server.
					UploadHandler uploadH = new UploadHandler(CivicinityMyView.this);
					uploadH.upload(mReturnID, true);
					
					// move to mainpage
					finish();
					Intent intent = new Intent(CivicinityMyView.this, CivicinityMainpage.class);
					intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
					startActivity(intent);
                }
            });
            
            mDialog.dismiss();
            
            // ask something...
            //new syncWithLocalDatabase().execute();
        }
    }
}
